其他
如何将 @Transactional 事务注解运用到炉火纯青?
前两天在工作中忙的焦头烂额,涉及到@Transactional
对于事务的控制,便仔细研究了一下,颇有所获,花费好了几天测试整理,今天才发表出来,希望看到博客的老铁们能有所获吧。话不多说直奔正题。
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition
定义中包括了如下几个表示传播行为的常量:
TransactionDefinition.PROPAGATION_REQUIRED
:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。TransactionDefinition.PROPAGATION_REQUIRES_NEW
:创建一个新的事务,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_SUPPORTS
:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。TransactionDefinition.PROPAGATION_NOT_SUPPORTED
:以非事务方式运行,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_NEVER
:以非事务方式运行,如果当前存在事务,则抛出异常。TransactionDefinition.PROPAGATION_MANDATORY
:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。TransactionDefinition.PROPAGATION_NESTED
:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED
。
unchecked exception
回滚。Spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback
(Spring默认取决于是否抛出runtimeException
)。try{}catch(Exception e){}
处理,那么try里面的代码块就脱离了事务的管理,若要事务生效需要在catch中throw new RuntimeException ("xxxxxx");
这一点也是面试中会问到的事务失效的场景。@Transactional
注解底层实现方式吧,毫无疑问,是通过动态代理,那么动态代理又分为JDK自身和CGLIB,这个也不多赘述了,毕竟今天的主题是如何将@Transactional
对于事物的控制应用到炉火纯青。哈哈~@Transactional
注解的方法中,再调用本类中的其他方法method2时,那么method2方法上的@Transactional
注解是不!会!生!效!的!但是加上也并不会报错,拿图片简单帮助理解一下吧。这一点也是面试中会问到的事务失效的场景。可见目标对象内部的自我调用,也就是通过this.指向的目标对象将不会执行方法的增强。
先说第二点需要注意的地方,等下说如何解决上面第一点的问题。第二点就是@Transactional
注解的方法必须是公共方法,就是必须是public修饰符!!!另外,公众 号Java精选,回复java面试,获取面试资料。
controller
层直接调用没有接口的service层,加了注解也一样不起作用吧,这个懒了,没有测试,其一是因为没有人会这么开发吧,其二是我就认为是不起作用的,哈哈AopContext.currentProxy ()
获取到本类的代理对象,再去调用就好啦。因为这个是CGLIB实现,所以要开启AOP,当然也很简单,在springboot启动类上加上注解@EnableAspectJAutoProxy(exposeProxy = true)
就可以啦,这个依赖大家自行搜一下就好啦。要注意,注意,代理对象调用的方法也要是public修饰符,否则方法中获取不到注入的bean,会报空指针错误。@RestController
public class TransactionalController {
@Autowired
private TransactionalService transactionalService;
@PostMapping("transactionalTest")
public void transacionalTest(){
transactionalService.transactionalMethod();
}
}
Service中实现对事务的控制:接口
public interface TransactionalService {
void transactionalMethod();
}
transactionalMethod
都处在一个事务中,四条更新操作全部失败。@Transactional
注解呢?答案是结果和上面是一致的。transactionalMethod
上有注解,并且方法1和方法2都处于当前事务中(不使用代理调用,方法1和方法2上的@Transactional
注解是不生效的;使用代理,需要方法1和方法2都处在transactionalMethod
方法的事务中,默认或者嵌套事务均可,当然也可以不加@Transactional
注解),那么整体保持事务一致性。@Transactional
注解是不生效的,所以一定要使用代理调用实现,然后让方法1和方法2分别单独开启新的事务,便OK啦。下面摆上图片。transactionalMethod
方法中分别对方法1和方法2进行控制。要将代码的艺术发挥到极致嘛,下面装逼开始。@Transactioinal
注解的使用就到此为止啦,@Transactional
注解保证的是每个方法处在一个事务,如果有try一定在catch中抛出运行时异常。作者:范学博
https://blog.csdn.net/fanxb92/article/details/81296005
最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!
(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题!
特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,「大咖笔记」,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注。